目前dome已经做好啦,但是感觉自己理解还不是很透彻。打算改下自己的博客从头开始对博客进行重新更新,更新时间7/16/2016。
下面给出界面优化知识思维导图
今天也打算写关于图片、音频和视频在深层原理,以及图像在屏幕显示原理以及后面提出如何进行在此方面优化。
下面就讲述在IOS开发过程中经常使用的UIView和CALayer两者之间的关系和在动画使用过程的具体封装(网上也有许多关于这个话题的文章,也是站在巨人肩膀上)。
UIView 和 CALayer之间的关系
打开 UIView
和 CALyer
中实际实现的代码,下面是UIView
实现源码:
UIView
头文件:
1 | NS_CLASS_AVAILABLE_IOS(2_0) @interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusEnvironment> |
CALayer
源文件:
1 | //CALayer实现源码: |
我们可以看出 UIView
是继承自 UIResponder
,而 CALayer
继承自NSObject
。这也是 UIView
可以相应触摸事件,并实现响应链中最后一环所在后面我们会具体讲述。CALayer
继承自 NSObject
,其中 UIView
中又包含自己所特有的 layer
。我们可以看做 CALayer
是 UIView
的具体内容细节的实现,两者具有平行关系。
为什么不把两者何在一起进行实现呢,分开实现具体功能呢?
我想可能是为啦分层需要,把功能具体分隔开来。UIView实现触摸响应,CALayer实现具体的内容展示。
下面我们将写关于 UIView
和 CALayer
的一些相关的知识:
列出在 UIView
实现不了的 CALayer
的功能:
- 阴影,圆角,带颜色的边框
- 3D变换
- 非矩形范围
- 透明遮罩
- 多级非线性动画
我们也都知道在 iPhone
手机内存是固定不能进行拓展,所以我们手机内存是很宝贵的。如果我们想要加载大容量的图片,会占用很大的内存。
为此,Apple
采用了一种比较巧妙的策略。在低内存的情况下,系统会强制清除 UIImage
对象所指向的图片数据,以释放部分内存。注意,这种清除行为影响到的只是图片数据,而不会影响到 UIImage
对象本身。当我们需要绘制那些图片数据已经被清除的UIImage
对象时,对象会自动从源文件中重新加载数据。当然,这是以时间换空间的一种策略,会导致一定的性能损耗。下面给出一些图片处理小技巧
UIImage缓存
我们知道在使用 imageNamed
进行图片显示,图片会缓存。但具体缓存是怎么实现,其中解析和清除时间是什么时候呢?
当我们使用
imageNamed:
时创建图片,系统会通过Bundle
的文件中找到图片的文件名,然后把相关的名字放到UIImage
返回,此时并没有解析图片。当图片在第一次显示时,图片才会调用内部解码方法,解码会放到一个全局变量中。图片在解码后,会在App
第一次进入后台或者内存警告时,该图片的缓存才会被清空,其他情况缓存会一直存在。
使用 imageWithData
可以避免缓存吗?
我们在创建 UIImage
时,UIImage
的底层会调用 ImageIO
的CGImageSourceCreateWithData()
,此方法有个参数 ShouldCache
,在 64 位的处理器上是默认开启的。图片也会在第一次显示在屏幕上才会被解码,解码数据也会保存在CGimage
的内部。
但是与上面使用 imageName
的情况不同,在 UIImage
被释放是其缓存也会进行释放。
怎样避免缓存
- 上面我们可以看到如果直接使用
CGImageSourceCreateWithData()
,并且关闭ShouldCache
和ShouldCacheImmediately
,但是这样的话每次图片需要显示的话,都会进行图片解码,这样会占用较大CPU
- 把图片用
CGContextDrawImage()
绘制到画布上,然后把画布的数据取出来当作图片。这也是常见的网络图片库的做法。
后面小编将分出一篇文章专门讲述空间绘制的博文。
参考资料:
处理图片的一些小 Tip
内存恶鬼drawRect
图层的树状结构
寄宿图
UIView和CALayer总的参考地址
UIVie和CALayer关系源码;